﻿using System;
using System.Data;
using System.Web;
using SAFE.Utilities.DataAccess;
using SAFE.Utilities.Authentication;
using System.Web.Security;

namespace SafeAPI
{

    #region ENUMS

    public enum USERTYPE
    {
        USER = 0,
        PERSON = 1
    }

    public enum AUTHENTICATETYPE
    {
        SAFE = 0,
        WINDOWS = 1,
        LDAP = 2,
        CUSTOM = 3,
        EXTERNAL = 4
    }

    #endregion

    #region Authenticate Code

    public class Authentication
    {
        public Authentication()
        {
            dbmanager = new QSecuredbManager("SAFEDB");
        }

        #region Private Variables

        private QSecuredbManager dbmanager = null;
        private USERTYPE _UserType = USERTYPE.USER;
        private AUTHENTICATETYPE _AuthenticateType = AUTHENTICATETYPE.SAFE;
        private const string PERSONCOLUMNS = "*";
        private const string USERCOLUMNS = "*";
        private bool _IsAuthenticated = false;
        private string _UserName = "";
        private string _Password = "";
        private string _ExternalUserNameHeader = "";
        private string _CustomUserField = "";
        private string _CustomPasswordField = "";
        private string _CustomAuthObject = "";
        private string _LDAPDomain = "";
        private string _LDAPLoginField = "";
        private string _LDAPUserName = "";
        private string _LDAPPassword = "";

        #endregion

        #region Private Methods

        DataRow CustomAuthenticate()
        {
            string SQL = "";
            DataRow drReturn = null;

            SQL = "SELECT * FROM {0} WHERE {1}={2} AND {3}={4}";
            SQL = string.Format(SQL, _CustomAuthObject, _CustomUserField, _UserName, _CustomPasswordField, _Password);
            drReturn = dbmanager.GetDataRow(SQL);

            if (drReturn is DataRow)
            {
                if (_UserType == USERTYPE.USER)
                {
                    SQL = "SELECT {0} FROM USERS WHERE LoginID={1}";
                    SQL = string.Format(SQL, USERCOLUMNS, _UserName);
                }
                else
                {
                    SQL = "SELECT {0} FROM PERSONS WHERE UserName={1}";
                    SQL = string.Format(SQL, PERSONCOLUMNS, _UserName);
                }
                drReturn = dbmanager.GetDataRow(SQL);
            }
            return drReturn;
        }

        DataRow Authenticate()
        {
            string SQL = "";
            DataRow drReturn = null;
            if (_UserType == USERTYPE.USER)
            {
                if (_AuthenticateType == AUTHENTICATETYPE.SAFE)
                {
                    SQL = "SELECT {0} FROM USERS WHERE LoginID={1} AND Password={2}";
                    SQL = string.Format(SQL, USERCOLUMNS, _UserName, _Password);
                }
                else
                {
                    SQL = "SELECT {0} FROM USERS WHERE LoginID={1}";
                    SQL = string.Format(SQL, PERSONCOLUMNS, _UserName);
                }
                drReturn = dbmanager.GetDataRow(SQL);
            }
            else
            {
                if (_AuthenticateType == AUTHENTICATETYPE.SAFE)
                {
                    if (_CustomPasswordField.Length == 0)
                    {
                        throw new Exception("Cannot Authenticate to SAFE without Password Field of PersonType");
                    }
                    if (_Password.Length == 0)
                    {
                        throw new Exception("Cannot Authenticate to SAFE without Password of PersonType");
                    }
                    SQL = "SELECT * FROM PERSONS WHERE UserName={0} AND {1}={2}";
                    SQL = string.Format(SQL, _UserName, _CustomPasswordField, _Password);
                }
                else
                {
                    SQL = "SELECT * FROM PERSONS WHERE UserName={0}";
                    SQL = string.Format(SQL, _UserName);
                }
                drReturn = dbmanager.GetDataRow(SQL);
            }
            return drReturn;
        }


        #endregion

        #region public Properties

        public USERTYPE UserType
        {
            set
            {
                _UserType = value;
            }
            get
            {
                return _UserType;
            }
        }

        public AUTHENTICATETYPE AuthenticateType
        {
            set
            {
                _AuthenticateType = value;
            }
            get
            {
                return _AuthenticateType;
            }
        }

        public bool IsAuthenticated
        {
            get
            {
                return _IsAuthenticated;
            }
        }

        public string UserName
        {
            set
            {
                _UserName = value;
            }
            get
            {
                return _UserName;
            }
        }

        public string Password
        {
            set
            {
                _Password = value;
            }
        }

        #endregion

        #region Public Methods

        public bool SignIn()
        {
            _IsAuthenticated = false;
            DataRow drUser = null;
            
            switch (_AuthenticateType)
            {
                case AUTHENTICATETYPE.SAFE:
                    #region SAFE

                    if (_UserName.Length == 0 || _Password.Length == 0)
                    {
                        throw new Exception("SAFE Authentication requires UserName and Password.");
                    }
                    drUser = Authenticate();
                    if (drUser is DataRow)
                    {
                        _IsAuthenticated = true;
                    }
                    break;

                    #endregion
                case AUTHENTICATETYPE.WINDOWS:
                    #region WINDOWS

                    string UserIdentity = HttpContext.Current.User.Identity.Name;
                    string[] UserInfo = UserIdentity.Split('\\');
                    if (UserInfo.Length > 1)
                    {
                        _UserName = UserInfo[1];
                    }
                    else
                    {
                        _UserName = UserIdentity;
                    }

                    if (_UserName.Length == 0)
                    {
                        throw new Exception("No Windows User is Authenticated.");
                    }

                    drUser = Authenticate();
                    if (drUser is DataRow)
                    {
                        _IsAuthenticated = true;
                    }

                    break;

                    #endregion
                case AUTHENTICATETYPE.LDAP:
                    #region LDAP

                    QSecureLDAPAuthenticate ldap = new QSecureLDAPAuthenticate();
                    ldap.SetAuthenticationType(System.DirectoryServices.AuthenticationTypes.Secure);
                    ldap.SetDomain(_LDAPDomain);

                    if (_LDAPLoginField.Length > 0)
                    {
                        ldap.SetUser(_LDAPUserName);
                        ldap.SetPass(_LDAPPassword);
                        UserName = ldap.GetUserName(_LDAPLoginField, _UserName);
                    }
                    else
                    {
                        UserName = _UserName;
                    }

                    ldap.SetUser(_UserName);
                    ldap.SetPass(_Password);

                    _UserName = ldap.GetUserName("samaccountname", _UserName);

                    break;

                    #endregion
                case AUTHENTICATETYPE.CUSTOM:
                    #region CUSTOM

                    if (_UserName.Length == 0)
                    {
                        throw new Exception("Custom Authentication requires atleast UserName.");
                    }
                    drUser = CustomAuthenticate();
                    if (drUser is DataRow)
                    {
                        _IsAuthenticated = true;
                    }
                    break;

                    #endregion
                case AUTHENTICATETYPE.EXTERNAL:
                    #region EXTERNAL

                    if (_ExternalUserNameHeader.Length == 0)
                    {
                        throw new Exception("External User HeaderName is missing.");
                    }
                    string ExternalUserName = HttpContext.Current.Request.Headers[_ExternalUserNameHeader];
                    if (string.IsNullOrEmpty(ExternalUserName))
                    {
                        throw new Exception("External User is not Authenticated.");
                    }
                    else
                    {
                        _UserName = ExternalUserName;
                    }
                    drUser = Authenticate();
                    if (drUser is DataRow)
                    {
                        _IsAuthenticated = true;
                        
                    }
                    break;

                    #endregion
            }

            
            return _IsAuthenticated;
        }

        #endregion


    }


    #endregion
}